﻿using System;

namespace paiban.data
{
    using ExcelConfig;
    using ExcelConfig.StoreAPI;

    public class WorkPersonInfo
    {
        internal string config_name = "banbiao";
        internal List<string> exclude_persons;
        internal int year;
        internal int month;
        internal string[] unworktags;
        internal int days;
        internal string[] banbiao;
        internal string[] person_map;
        internal int person_count;
        internal string[] work_person_map;
        internal int work_person_count;
        internal string[] dasao_workname;
        public WorkPersonInfo(string name)
        {
            this.config_name = name;
            
            year = (int)cgsys.config.Number("年份");
            month = (int)cgsys.config.Number("月份");
            exclude_persons = new List<string>(cgsys.config.Array("排除人员"));
            unworktags = cgsys.config.Array("不工作标识");
            dasao_workname = cgsys.config.Array("打扫班标识");
            if (dasao_workname.Length == 0) dasao_workname.Append("晚"); //兼容
            days = calc_monthdays();
            Load();
        }
        public void MoveBanbiao()
        {
            var buf = new string[days];
            Array.Copy(banbiao, banbiao.Length - days, buf, 0, days);
            Array.Copy(banbiao, 0, banbiao, days, banbiao.Length - days);
            Array.Copy(buf, 0, banbiao, 0, days);
            var pe= person_map[person_map.Length -1];
            Array.Copy(person_map, 0, person_map, 1, person_map.Length -1);
            person_map[0] = pe;
            for (int i = 0, j = 0; i < person_count; i++) if (!exclude_persons.Contains(person_map[i])) work_person_map[j++] = person_map[i];
        }
        public IEnumerable<string> ReadWorkPerson(int day)
        {
            for (var i = 0; i < work_person_count; i++) if (!unworktags.Contains(ReadDay(work_person_map[i], day))) yield return work_person_map[i];
        }
        public IEnumerable<string> ReadWanbanPerson(int day)
        {
            for (var i = 0; i < work_person_count; i++) if (!unworktags.Contains(ReadDay(work_person_map[i], day)) && (dasao_workname.Contains(ReadDay(work_person_map[i], day)))) yield return work_person_map[i];
        }
        public IEnumerable<string> ReadNotWanbanPerson(int day)
        {
            for (var i = 0; i < work_person_count; i++) if (!unworktags.Contains(ReadDay(work_person_map[i], day)) && !(dasao_workname.Contains(ReadDay(work_person_map[i], day)))) yield return work_person_map[i];
        }
        public string ReadDay(string person, int day)
        {
            var ix = Array.IndexOf(person_map, person);
            if (ix == -1) throw new ArgumentException($"not person ({person}) at day {day}.");

            return banbiao[ix * days + (day - 1)];
        }
        public IEnumerable<int> LoopDays()
        {
            for (var i = 1; i <= days; i++) yield return i;
        }
        public IEnumerable<int> LoopLast5Days()
        {
            for (var i = days-5; i <= days; i++) yield return i;
        }
        public IEnumerable<int> LoopBeforeLast5Days()
        {
            for (var i = 1; i < days - 5; i++) yield return i;
        }
        public IEnumerable<string> LoopWorkPersons()
        {
            for (var i = 0; i < work_person_count; i++) yield return work_person_map[i];
        }
        internal void Load()
        {
            var file = new ExcelStreamFile(ConfigStoreAPI.Download(cgsys.config_zone, config_name));
            file.ToSheet("Sheet1");
            file.SetKeyField(file.Read(1, 1).Text);

            var i = 2;
            int j = 0;
            var p_queue = new Queue<string>();
            var person = string.Empty;
            while (!string.IsNullOrEmpty(person = file.Read(i++, 1).Text)) p_queue.Enqueue(person);

            person_count = p_queue.Count;
            person_map = new string[person_count];
            banbiao = new string[person_count * days];
            i = 0;
            var workperson_count = person_count;
            foreach (var line in file.ReadAllLine())
            {
                person = p_queue.Dequeue();
                person_map[i] = person;
                if (person =="日期") exclude_persons.Add(person);
                else if (string.IsNullOrEmpty(line.Text("1"))) exclude_persons.Add(person);
                if (exclude_persons.Contains(person)) workperson_count--;

                for (j = 1; j <= days; j++) banbiao[i * days + (j - 1)] = line.Text(j.ToString());
                i++;
            }

            work_person_map = new string[workperson_count];
            for (i = 0, j = 0; i < person_count; i++) if (!exclude_persons.Contains(person_map[i])) work_person_map[j++] = person_map[i];
            work_person_count = workperson_count;
        }
        internal int calc_monthdays()
        {
            return new DateTime(year, month, 1).AddMonths(1).AddDays(-1).Day;
        }
    }
}
